using Microsoft.AspNetCore.SignalR;
using RealtimeCollabGame.Application.Services;
using RealtimeCollabGame.Application.Commands;
using RealtimeCollabGame.Application.DTOs;
using RealtimeCollabGame.Domain.Enums;

namespace RealtimeCollabGame.Infrastructure.SignalR;

public class GameHub : Hub
{
    private readonly GameService _gameService;
    private static readonly Dictionary<string, string> _userConnections = new();

    public GameHub(GameService gameService)
    {
        _gameService = gameService;
    }

    public override async Task OnConnectedAsync()
    {
        await base.OnConnectedAsync();
        Console.WriteLine($"客户端连接: {Context.ConnectionId}");
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        // 清理用户连接
        var userId = _userConnections.FirstOrDefault(x => x.Value == Context.ConnectionId).Key;
        if (userId != null)
        {
            _userConnections.Remove(userId);
        }

        await base.OnDisconnectedAsync(exception);
        Console.WriteLine($"客户端断开连接: {Context.ConnectionId}");
    }

    public async Task JoinGame(string gameCode, string playerNickName, string? password = null)
    {
        try
        {
            Console.WriteLine($"玩家 {playerNickName} 尝试加入房间 {gameCode}");

            var command = new JoinGameCommand(gameCode, playerNickName, password);
            var game = await _gameService.JoinGameAsync(command);

            // 加入SignalR组
            await Groups.AddToGroupAsync(Context.ConnectionId, gameCode);

            // 记录用户连接
            var player = game.Players.FirstOrDefault(p => p.NickName == playerNickName);
            if (player != null)
            {
                _userConnections[player.Id.ToString()] = Context.ConnectionId;
            }

            // 通知所有玩家（包括房主）
            await Clients.Group(gameCode).SendAsync("PlayerJoined", player);

            // 发送游戏状态给新玩家
            await Clients.Caller.SendAsync("GameJoined", game);

            Console.WriteLine($"玩家 {playerNickName} 成功加入房间 {gameCode}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"玩家 {playerNickName} 加入房间 {gameCode} 失败: {ex.Message}");
            await Clients.Caller.SendAsync("Error", ex.Message);
        }
    }

    public async Task LeaveGame(string gameCode, string playerId)
    {
        try
        {
            await Groups.RemoveFromGroupAsync(Context.ConnectionId, gameCode);
            _userConnections.Remove(playerId);

            await Clients.Group(gameCode).SendAsync("PlayerLeft", playerId);
        }
        catch (Exception ex)
        {
            await Clients.Caller.SendAsync("Error", ex.Message);
        }
    }

    public async Task PaintAction(string gameCode, string playerId, int x, int y, int brushSize)
    {
        try
        {
            Console.WriteLine($"收到涂色动作: gameCode={gameCode}, playerId={playerId}, x={x}, y={y}, brushSize={brushSize}");

            // 先通过房间码获取游戏
            var game = await _gameService.GetGameByCodeAsync(gameCode);
            if (game == null)
            {
                Console.WriteLine($"游戏不存在: {gameCode}");
                await Clients.Caller.SendAsync("Error", "游戏不存在");
                return;
            }

            Console.WriteLine($"找到游戏: {game.Id}, 状态: {game.Status}, 玩家数量: {game.Players.Count}");

            // 尝试解析playerId为Guid，如果失败则尝试通过昵称查找玩家
            Guid playerGuid;
            if (!Guid.TryParse(playerId, out playerGuid))
            {
                Console.WriteLine($"playerId不是Guid格式，尝试通过昵称查找: {playerId}");
                // 如果playerId不是Guid格式，尝试通过昵称查找玩家
                var player = game.Players.FirstOrDefault(p => p.NickName == playerId);
                if (player == null)
                {
                    Console.WriteLine($"玩家不存在: {playerId}");
                    await Clients.Caller.SendAsync("Error", "玩家不存在");
                    return;
                }
                playerGuid = player.Id;
                Console.WriteLine($"通过昵称找到玩家: {playerGuid}");
            }
            else
            {
                Console.WriteLine($"playerId是Guid格式: {playerGuid}");
            }

            // 检查游戏状态
            if (game.Status != GameStatus.Playing)
            {
                Console.WriteLine($"游戏状态不正确: {game.Status}, 期望: Playing");
                await Clients.Caller.SendAsync("Error", "游戏未开始或已结束");
                return;
            }

            // 检查玩家是否在游戏中
            var playerInGame = game.Players.FirstOrDefault(p => p.Id == playerGuid);
            if (playerInGame == null)
            {
                Console.WriteLine($"玩家不在游戏中: {playerGuid}");
                await Clients.Caller.SendAsync("Error", "玩家不在房间中");
                return;
            }

            Console.WriteLine($"准备处理涂色动作: gameId={game.Id}, playerId={playerGuid}, x={x}, y={y}, brushSize={brushSize}");

            var command = new PaintActionCommand(
                game.Id,
                playerGuid,
                x, y, brushSize
            );

            await _gameService.ProcessPaintActionAsync(command);

            Console.WriteLine($"涂色动作处理成功，广播给其他玩家");

            // 广播涂色动作给所有玩家
            await Clients.OthersInGroup(gameCode).SendAsync("PaintActionReceived", new
            {
                PlayerId = playerGuid.ToString(),
                X = x,
                Y = y,
                BrushSize = brushSize,
                Timestamp = DateTime.UtcNow
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine($"PaintAction处理失败: {ex.Message}");
            Console.WriteLine($"异常详情: {ex}");
            await Clients.Caller.SendAsync("Error", ex.Message);
        }
    }

    public async Task StartGame(string gameCode, string playerId)
    {
        try
        {
            Console.WriteLine($"开始游戏: {gameCode}");

            // 获取游戏信息
            var game = await _gameService.GetGameByCodeAsync(gameCode);
            if (game == null)
            {
                Console.WriteLine($"游戏不存在: {gameCode}");
                await Clients.Caller.SendAsync("Error", "游戏不存在");
                return;
            }

            Console.WriteLine($"找到游戏: {game.Id}, 状态: {game.Status}, 玩家数量: {game.Players.Count}");

            // 检查游戏状态
            if (game.Status != GameStatus.Waiting)
            {
                Console.WriteLine($"游戏状态不正确: {game.Status}, 期望: Waiting");
                await Clients.Caller.SendAsync("Error", "游戏状态不正确");
                return;
            }

            // 检查玩家数量
            if (game.Players.Count < 2)
            {
                Console.WriteLine($"玩家数量不足: {game.Players.Count}");
                await Clients.Caller.SendAsync("Error", "至少需要2名玩家才能开始游戏");
                return;
            }

            // 检查所有玩家是否准备
            var notReadyPlayers = game.Players.Where(p => !p.IsReady).ToList();
            if (notReadyPlayers.Any())
            {
                Console.WriteLine($"有玩家未准备: {string.Join(", ", notReadyPlayers.Select(p => p.NickName))}");
                await Clients.Caller.SendAsync("Error", "所有玩家必须准备才能开始游戏");
                return;
            }

            // 尝试解析playerId为Guid，如果失败则尝试通过昵称查找玩家
            Guid playerGuid;
            if (!Guid.TryParse(playerId, out playerGuid))
            {
                // 如果playerId不是Guid格式，尝试通过昵称查找玩家
                var player = game.Players.FirstOrDefault(p => p.NickName == playerId);
                if (player == null)
                {
                    await Clients.Caller.SendAsync("Error", "玩家不存在");
                    return;
                }
                playerGuid = player.Id;
            }

            // 检查是否是房主
            if (game.HostId != playerGuid)
            {
                await Clients.Caller.SendAsync("Error", "只有房主可以开始游戏");
                return;
            }

            // 开始游戏
            var startGameCommand = new StartGameCommand(game.Id, currentPlayer.Id);
            await _gameService.StartGameAsync(startGameCommand);

            Console.WriteLine($"游戏开始成功: {gameCode}");

            // 通知所有玩家游戏开始
            await Clients.Group(gameCode).SendAsync("GameStarted", new
            {
                GameCode = gameCode,
                GameDuration = game.GameDuration,
                StartedAt = DateTime.UtcNow
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine($"开始游戏失败: {ex.Message}");
            Console.WriteLine($"异常详情: {ex}");
            await Clients.Caller.SendAsync("Error", ex.Message);
        }
    }

    public async Task SendMessage(string gameCode, string playerId, string message)
    {
        await Clients.OthersInGroup(gameCode).SendAsync("MessageReceived", new
        {
            PlayerId = playerId,
            Message = message,
            Timestamp = DateTime.UtcNow
        });
    }

    public async Task SetReady(string gameCode, string playerId, bool isReady)
    {
        try
        {
            Console.WriteLine($"玩家 {playerId} 设置准备状态: {isReady}");

            // 先通过房间码获取游戏
            var game = await _gameService.GetGameByCodeAsync(gameCode);
            if (game == null)
            {
                await Clients.Caller.SendAsync("Error", "游戏不存在");
                return;
            }

            // 尝试解析playerId为Guid，如果失败则尝试通过昵称查找玩家
            Guid playerGuid;
            if (!Guid.TryParse(playerId, out playerGuid))
            {
                // 如果playerId不是Guid格式，尝试通过昵称查找玩家
                var player = game.Players.FirstOrDefault(p => p.NickName == playerId);
                if (player == null)
                {
                    await Clients.Caller.SendAsync("Error", "玩家不存在");
                    return;
                }
                playerGuid = player.Id;
            }

            // 设置玩家准备状态
            await _gameService.SetPlayerReadyAsync(game.Id, playerGuid, isReady);

            // 获取更新后的游戏状态
            var updatedGame = await _gameService.GetGameAsync(game.Id);
            if (updatedGame == null)
            {
                await Clients.Caller.SendAsync("Error", "游戏不存在");
                return;
            }

            // 通知所有玩家（包括调用者）准备状态变更
            await Clients.Group(gameCode).SendAsync("PlayerReady", playerGuid.ToString(), isReady);

            // 发送更新后的游戏状态给所有玩家
            await Clients.Group(gameCode).SendAsync("GameJoined", updatedGame);

            Console.WriteLine($"玩家 {playerId} 准备状态设置成功: {isReady}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"玩家 {playerId} 设置准备状态失败: {ex.Message}");
            await Clients.Caller.SendAsync("Error", ex.Message);
        }
    }
}